#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Time    : 2022/2/18 17:02
# @Author  : afraidbenq
# @File    : showdoc_reader.py
# @Software: PyCharm
# @Github  : github/afraidbenq
# @Email   : 329189987@qq.com
# @Desc    :
import os
import re
import json
from ruamel import yaml

import requests
from googletrans import Translator  # pip install 'googletrans==4.0.0rc1' 谷歌翻译的第三方包
from ruamel.yaml import RoundTripLoader, RoundTripDumper
from config import Config
from common import logger

# 浏览器头
headers = {'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
           'Connection': 'keep-alive',
           'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36'
                         ' (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'}


class ShowDoc(object):
    def __init__(self, project_info):
        self.project_info = project_info
        self.project_name = project_info["project_name"]
        self.url = project_info["api_docs_url"]
        self.username = project_info["account"]
        self.password = project_info["password"]
        self.cookie = self.login()
        headers["cookie"] = self.cookie
        # 过滤不使用的模块 和 页面
        self.filter_cat_id_list = ["161", "165", "173", "175", "176", "168", "172", "174"]  # 过滤台账、申报、管理计划
        self.filter_page_id_list = ["1634", "1637"]  # 过滤消息通知/wss的请求
        # 执行同步
        self.sync_showdoc(project_info["item_id"])  # 默认7

    def login(self):
        data = {"username": self.username, "password": self.password}
        r = requests.post(self.url + "/server/index.php?s=/api/user/login", data=data,
                          headers=headers)
        # 将CookieJar转为字典：
        cookiedict = requests.utils.dict_from_cookiejar(r.cookies)
        cookie = '__cfduid=d224404b4d2012a711cb57b6e910b43b61608127156; think_language=zh-CN; PHPSESSID={}; ' \
                 'cookie_token={}'.format(cookiedict['PHPSESSID'], cookiedict['cookie_token'])
        return cookie

    def get_item_list(self):
        r = requests.get(self.url + "/server/index.php?s=/api/item/myList", headers=headers)
        item_list = r.json()['data']
        for i in item_list:
            logger.info("item_id:{}, {}".format(i['item_id'], i['item_name']))

    def get_item_info(self, item_id):
        data = {"item_id": item_id}
        r = requests.post(self.url + "/server/index.php?s=/api/item/info", data=data, headers=headers)
        api_doc = r.json()['data']
        logger.info(api_doc)
        # menu_list = api_doc['menu']['catalogs']
        # for i in menu_list:
        #     logger.info(i)
        return api_doc

    def get_page_info(self, page_id):
        data = {"page_id": page_id}
        r = requests.post(self.url + "/server/index.php?s=/api/page/info", data=data, headers=headers)
        page_data = r.json()['data']
        page_content = r.json()['data']['page_content']
        page_content_replace = r.json()['data']['page_content'].replace("*", "").replace("\r", "").replace("\n",
                                                                                                           "").replace(
            "：", "") \
            .replace(" ", "").replace("`", "").replace("-", "").replace(":", "")
        return page_data, page_content, page_content_replace

    def gen_test_case(self, pages, mudule_name, case_mudule_path):
        # 查询path下原有的文件
        file_list = []
        for file in os.listdir(case_mudule_path):
            if file.endswith('yaml'):
                file_list.append(file)
        # logger.info(file_list)
        # 在模块内查找是否有子页面
        for j in pages:
            logger.info(j)
            if j['page_id'] in self.filter_page_id_list:
                continue
            page_data, page_content, page_content_replace = self.get_page_info(j["page_id"])
            allureStory = page_data["page_title"]
            # logger.info(page_data)
            # logger.info(page_content_replace)
            api = {"case_common": {"allureEpic": self.project_info["allureEpic"],
                                   "allureFeature": mudule_name,
                                   "allureStory": allureStory}}
            path = "/" + re.findall(r"/(.*?)`", page_content)[-1].replace(" ", "")
            method = re.findall(r"请求方式[a-zA-Z]{3,4}", page_content_replace)[-1].replace(" ", "")[4:]
            case_name = (path.replace("/", "_") + "_01")[1:]
            api[case_name] = {}
            api[case_name].update({"projectName": self.project_name})
            api[case_name].update({"url": path})
            if path.split('/')[1] == 'api':
                api[case_name].update({"host": "$cache{host3}"})
            else:
                api[case_name].update({"host": "$cache{host}"})
            api[case_name].update({"method": method.upper()})
            api[case_name].update({"detail": allureStory})
            if method.upper() == 'GET':
                api[case_name].update({"headers": {"Content-Type": "application/x-www-form-urlencoded",
                                                   "authentication": "$cache{authentication}"}})
                api[case_name].update({"requestType": "PARAMS"})
            elif method.upper() == 'POST':
                api[case_name].update({"headers": {"Content-Type": "application/json; charset=UTF-8",
                                                   "authentication": "$cache{authentication}"}})
                api[case_name].update({"requestType": "JSON"})
            else:
                api[case_name].update({"headers": {"authentication": "$cache{authentication}"}})
                api[case_name].update({"requestType": "NONE"})
            param = re.findall(r"说明(.*?)\|返回", page_content_replace)
            if len(param) == 0:
                data = {}
            else:
                request_body = {}
                param2 = param[0][5:].split("||")[1:]
                for p in param2:
                    if p == "":
                        continue
                    param3 = p.split("|")
                    if param3[0] == 'authentication':
                        continue
                    elif '&#8195' in param3[0]:
                        continue
                    elif param3[0] == 'page':
                        request_body[param3[0]] = 1
                    elif param3[0] == 'size':
                        request_body[param3[0]] = 10
                    else:
                        if param3[2] == "string":
                            request_body[param3[0]] = "string"
                        elif param3[2] == "int":
                            request_body[param3[0]] = 1
                        else:
                            request_body[param3[0]] = []
                data = request_body
            api[case_name].update({"is_run": True})
            api[case_name].update({"data": data})
            api[case_name].update({"dependence_case": False})
            api[case_name].update({"dependence_case_data": None})
            api[case_name].update({"assert": {"status_code": 200}})
            api[case_name].update({"current_request_set_cache": None})
            api[case_name].update({"sql": None})
            api[case_name].update({"teardown": None})
            api[case_name].update({"teardown_sql": None})
            # 生成测试用例yaml数据文件
            yaml_file = (path.replace('/', '_') + ".yaml")[1:]
            yaml_path = os.path.join(case_mudule_path, yaml_file)
            # 标记还需要的文件
            # logger.info(yaml_file)
            if yaml_file in file_list:
                file_list.remove(yaml_file)
            if not os.path.exists(yaml_path):
                with open(yaml_path, "w", encoding="utf-8") as f:
                    yaml.dump(api, f, Dumper=yaml.RoundTripDumper, allow_unicode=True)
            else:
                self.merged_yaml_data(yaml_path, api)
        # 删除多余接口文件
        if file_list:
            logger.info(f'旧版多余接口文件{file_list}')
            for file in file_list:
                file_path = os.path.join(case_mudule_path, file)
                logger.info(file_path)
                os.remove(file_path)

    def merged_yaml_data(self, yaml_path, api):
        with open(yaml_path, 'r', encoding="utf-8") as file:
            data1 = yaml.load(file, Loader=RoundTripLoader)
        data2 = api
        # 暂时只对用例里data、requestType数据进行处理，保留原始数据，并对新字段进行增量处理
        if len(data1.keys()) > 2:
            logger.warning("单用例文件内存在多个用例")
            return
        data1_data = data1[list(data1.keys())[-1]]['data']
        data2_data = data2[list(data2.keys())[-1]]['data']
        data1_requestType = data1[list(data1.keys())[-1]]['requestType']
        for k, v in data2_data.items():
            if k in data1_data.keys():
                data2[list(data2.keys())[-1]]['data'][k] = data1_data[k]
        data2[list(data2.keys())[-1]]['requestType'] = data1_requestType
        merged_data = {**data1, **data2}
        with open(yaml_path, 'w', encoding="utf-8") as file:
            documents = yaml.dump(merged_data, file, Dumper=RoundTripDumper, allow_unicode=True)

    def sync_showdoc(self, item_id):
        # 根据项目item_id获取模块树
        api_doc = self.get_item_info(item_id)
        # 生成项目目录
        case_data_path = os.path.join(Config.case_data_path, self.project_name)
        logger.info(case_data_path)
        logger.info(api_doc['menu']['catalogs'])
        if not os.path.exists(case_data_path):
            os.mkdir(case_data_path)
        # 遍历模块树
        for i in api_doc['menu']['catalogs']:
            if i['cat_id'] in self.filter_cat_id_list:
                continue
            mudule_name = i["cat_name"]
            logger.info(mudule_name)
            # 生成模块目录
            case_mudule_path = os.path.join(case_data_path, mudule_name)
            logger.info(case_mudule_path)
            if not os.path.exists(case_mudule_path):
                os.mkdir(case_mudule_path)
            pages = i["pages"]
            self.gen_test_case(pages, mudule_name, case_mudule_path)
            # 在模块内查找是否有子模块
            for k in i['catalogs']:
                if k['cat_id'] in self.filter_cat_id_list:
                    continue
                submodule_name = k["cat_name"]
                logger.info(f"{mudule_name}-子模块-{submodule_name}")
                # 生成子模块目录
                submodule_path = os.path.join(case_mudule_path, submodule_name)
                logger.info(submodule_path)
                if not os.path.exists(submodule_path):
                    os.mkdir(submodule_path)
                pages = k["pages"]
                self.gen_test_case(pages, mudule_name + "-" + submodule_name, submodule_path)
                # 在子模块内查找是否有孙模块
                for l in k['catalogs']:
                    if l['cat_id'] in self.filter_cat_id_list:
                        continue
                    sunmodule_name = l["cat_name"]
                    logger.info(f"{submodule_name}-孙模块-{sunmodule_name}")
                    # 生成孙模块目录
                    sunmodule_path = os.path.join(submodule_path, sunmodule_name)
                    logger.info(sunmodule_path)
                    if not os.path.exists(sunmodule_path):
                        os.mkdir(sunmodule_path)
                    pages = l["pages"]
                    logger.info(pages)
                    self.gen_test_case(pages, mudule_name + "-" + submodule_name + "-" + sunmodule_name, sunmodule_path)


if __name__ == '__main__':
    # project_name = "oiltour"
    project_name = "jingji"
    project_info = Config.project[project_name]
    print(project_info)
    ShowDoc(project_info)
    # 获取项目item_id
    # s.get_item_list()
    # 获取item_info
    # s.get_item_info('7')
